package cz.acies.uniql.sql.element;

import java.util.ArrayList;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.dom.DOMElement;


import cz.acies.uniql.dialect.Dialect;
import cz.acies.uniql.sql.UniQLExpr;
import cz.acies.uniql.sql.functions.SQLFunc;

public class UniQLField extends UniQLExpr
{
	private static final long serialVersionUID = -8807164083147106048L;
	
	private UniQLExpr expr = null;
	private String alias = null;
	
	/**
	 * Konstruktor tridy UniQLField.
	 */
	public UniQLField() {
	}

	/**
	 * Konstruktor tridy UniQLField.
	 * 
	 * @param dialect - dialect
	 */
	public UniQLField(Dialect dialect) {
		super(dialect);
		//this(dialect, null, null);
	}

	/**
	 * Konstruktor tridy UniQLField.
	 * 
	 * @param expr - expr
	 */
	public UniQLField(UniQLExpr expr) {
		this(expr, null);	
	}

	/**
	 * Konstruktor tridy UniQLField.
	 * 
	 * @param expr - expr
	 * @param alias - alias
	 */
	public UniQLField(UniQLExpr expr, String alias) {
		super();
		this.setExpr(expr);
		this.setAlias(alias);
	}
	
	// -----  -----------------------------------------------------------------

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#translate()
	 */
	public String translate() throws Exception {
		StringBuffer sb = new StringBuffer("");
		if (expr != null) {
			expr.setUniQLProperties(this);
			sb.append(expr.translate());
			if (alias != null && alias.length() > 0) {
				sb.append(" AS ").append(alias);
			}			
		}
		return sb.toString();
	}

	// -----  -----------------------------------------------------------------
	
	public UniQLExpr clear() {
		expr.clear(); expr = null;
		alias = null;
		return this;
	}

	
	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	@Override
	public Object clone() throws CloneNotSupportedException {
		Object clone = super.clone();
		assert clone instanceof UniQLField;
		((UniQLField)clone).setExpr((expr != null) ? (UniQLExpr)expr.clone() : null);
		((UniQLField)clone).setAlias(alias);
		return clone;
	}

	// -----  -----------------------------------------------------------------
	
	/**
	 * Navraci hodnotu alias.
	 * 
	 * @return - vraci hodnotu alias objeku Field
	 */
	public String getAlias() {
		return alias;
	}

	/**
	 * Zada hodnotu alias.
	 * 
	 * @param alias - nova hodnota alias
	 */
	public void setAlias(String alias) {
		this.alias = alias;
	}

	/**
	 * Zada hodnotu alias.
	 * 
	 * @param alias - alias
	 * 
	 * @return vraci objekt typu Field
	 */
	public UniQLField as(String alias) {
		this.alias = alias;
		return this;
	}
	
	/**
	 * Navraci hodnotu expr.
	 * 
	 * @return - vraci hodnotu expr
	 */
	public UniQLExpr getExpr() {
		return expr;
	}

	/**
	 * Zada hodnotu expr.
	 * 
	 * @param expr nova hodnota expr
	 */
	public void setExpr(UniQLExpr expr) {
		this.expr = expr;
	}

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#setDialect(cz.acies.uniql.dialect.Dialect)
	 */
	public void setDialect(Dialect dialect) {
		super.setDialect(dialect);
		if (expr != null) expr.setDialect(this.getDialect());
	}

	// -----  -----------------------------------------------------------------
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#transToXML()
	 */
	public String transToXML() throws Exception {
		DOMElement node = new DOMElement("UniQLField");
		transToXML(node);
		return node.asXML();
	}
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#transToXML(org.dom4j.dom.DOMElement)
	 */
	public DOMElement transToXML(DOMElement node) throws Exception {
		node.setName("UniQLField");
		if (expr != null) {
			try {
				String xml = expr.transToXML();
				Document doc = DocumentHelper.parseText(xml);
				Element root = doc.getRootElement();
				node.add(root);
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (alias != null && alias.length() > 0) {
				node.setAttribute("alias", alias);
			}
		}		
		return node;
	}

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#xmlToExpr(java.lang.String)
	 */
	public UniQLExpr xmlToExpr(String xml) throws Exception {
		return null;
	}

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#xmlToExpr(org.dom4j.Element)
	 */
	@Override
	@SuppressWarnings("unchecked")	
	public UniQLExpr xmlToExpr(Element node) throws Exception {
		String alias = node.attributeValue("alias");
		ArrayList<Element> params = new ArrayList<Element>(node.elements());
		for (int i = 0; i < params.size(); i++) {
			Element param = (Element)params.get(i);
			String nodename = param.getName();
			UniQLExpr expr = null; 
			if (nodename.trim().equals("UniQLColumn")) {
				expr = new UniQLColumn(getDialect()).xmlToExpr(param);
			} else if (nodename.trim().equals("UniQLValue")) {
				expr = new UniQLValue(getDialect()).xmlToExpr(param);
			} else if (nodename.trim().equals("UniQLCondition")) {
				expr = new UniQLCondition(getDialect()).xmlToExpr(param);
			} else if (nodename.trim().equals("SQLFunc")) {
				expr = new SQLFunc(getDialect()).xmlToExpr(param);				
			}
			if (expr != null) this.setExpr(expr);
		}
		if (alias != null && alias.length() > 0) {
			this.as(alias);
		}
		return this;
	}
	
	// -----  -----------------------------------------------------------------
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return "UniQLField( expr="+this.expr+", alias="+this.alias+" )";
	}
	/*
	public int hashCode() {
		int hash = -1; 
		if (this.getExpr() != null) hash += this.getExpr().hashCode();
		if (this.getAlias() != null) hash += this.getAlias().hashCode();
		return hash; 
	}
	*/
}
